﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.IO;
using System;
using UObject = UnityEngine.Object;

public class ResourcesManager : MonoBehaviour
{
    internal class BundleInfo
    {
        public string AssetsNmae;
        public string BundleName;
        public List<string> Dependences;
    }

    internal class BundleData {
        public AssetBundle Bundle;

        public int Count;
        public BundleData(AssetBundle ab)
        {
            Bundle = ab;
            Count = 1;
        }
    }


    //存放Bundle信息的集合
    private Dictionary<string, BundleInfo> m_BundleInfos = new Dictionary<string, BundleInfo>();
    //存放Bundle资源的集合
    private Dictionary<string, BundleData> m_AssetBundles = new Dictionary<string, BundleData>();

    

    /// <summary>
    /// 解析版本文件
    /// </summary>
    public void PraseVersionFile()
    {
        //1.拿到文件路径
        string url = Path.Combine(PathUtil.BundleResourcePath, Appconst.FileListName);

        //2.读取文件
        string[] data = File.ReadAllLines(url);

        //3.解析文件信息
        for(int i = 0; i < data.Length; i++)
        {
            BundleInfo bundleInfo = new BundleInfo();
            string[] info = data[i].Split('|');
            bundleInfo.AssetsNmae = info[0];
            bundleInfo.BundleName = info[1];
            //list本质上是数组，但可以动态扩容
            bundleInfo.Dependences = new List<string>(info.Length - 2);//依赖资源
            for (int j = 2; j < info.Length; j++)
                bundleInfo.Dependences.Add(info[j]);
            m_BundleInfos.Add(bundleInfo.AssetsNmae, bundleInfo);

            if (info[0].IndexOf("LuaScripts") > 0)
            {
                Manager.Lua.LuaNames.Add(info[0]);
            }
        }
    }


    //减去引用记数
    internal void MinusBundleCount(string assetName)
    {
        string bundleName = m_BundleInfos[assetName].BundleName;
        MinusOneBundleCount(bundleName);

        //依赖资源
        List<string> dependences = m_BundleInfos[assetName].Dependences;
        if (dependences != null)
        {
            foreach(string dependence in dependences)
            {
                string name = m_BundleInfos[dependence].BundleName;
                MinusOneBundleCount(name);
            }
        }
    }

    private void MinusOneBundleCount(string bundleName)
    {
        if(m_AssetBundles.TryGetValue(bundleName,out BundleData bundle))
        {
            if (bundle.Count > 0)
            {
                bundle.Count--;
                Debug.Log("bundle:"+bundleName+"引用次数-1，当前引用次数为:" + bundle.Count);
            }
            if (bundle.Count <= 0)
            {
                Debug.Log("bundle:" + bundleName + "放入对象池:" + bundleName);
                Manager.Pool.UnSpawn("AssetBundle", bundleName, bundle.Bundle);
                m_AssetBundles.Remove(bundleName);
            }
        }
    }

    /// <summary>
    /// 异步加载资源
    /// </summary>
    /// <param name="assetName">资源名</param>
    /// <param name="action">完成回调</param>
    /// <returns></returns>
    IEnumerator LoadBundleAsync(string assetName,Action<UObject> action=null)
    {
        //取出bundle名
        string bundleName = m_BundleInfos[assetName].BundleName;
        //拿到bundle路径
        string bunldePath = Path.Combine(PathUtil.BundleResourcePath, bundleName);
        //加载依赖资源
        List<string> dependences = m_BundleInfos[assetName].Dependences;
        //加载bundle
        BundleData bundle = GetBundle(bundleName);
        if (bundle == null)
        {
            UObject obj = Manager.Pool.Spawn("AssetBundle", bundleName);
            if (obj != null)
            {
                AssetBundle ab = obj as AssetBundle;
                bundle = new BundleData(ab);
            }
            else
            {
                AssetBundleCreateRequest request = AssetBundle.LoadFromFileAsync(bunldePath);
                yield return request;
                bundle = new BundleData(request.assetBundle);
                
            }
           m_AssetBundles.Add(bundleName, bundle);
        }
       if (dependences != null && dependences.Count > 0)
        {
            for(int i = 0; i < dependences.Count; i++)
            {
                yield return LoadBundleAsync(dependences[i]);
            }
        }
        //如果加载的是场景 则直接返回
        if (assetName.EndsWith(".unity"))
        {
            action?.Invoke(null);
            yield break;
        }

        //如果是依赖资源 则不需要调用回调资源
        if (action == null)
        {
            yield break;
        }

        //加载文件信息
        AssetBundleRequest bundleRequest = bundle.Bundle.LoadAssetAsync(assetName);

        //等待文件加载完成
        yield return bundleRequest;

        //调用回调,将资源传回应用层
        if (action != null&&bundleRequest!=null)
            action.Invoke(bundleRequest.asset);  
    }

    /// <summary>
    /// 提供同步的调用接口
    /// </summary>
    /// <param name="assetName"></param>
    /// <param name="action"></param>
    private void LoadAsset(string assetName,Action<UObject> action)
    {
#if UNITY_EDITOR
        if (Appconst.GameMode == GameMode.EditorMode)

            EditorLoadAsset(assetName, action);

        else
#endif
            StartCoroutine(LoadBundleAsync(assetName, action));//调用协程方法
    }

#if UNITY_EDITOR
    void EditorLoadAsset(string assetName, Action<UObject> action = null)
    {
        Debug.Log("编辑器模式");
        UObject obj = UnityEditor.AssetDatabase.LoadAssetAtPath(assetName, typeof(UObject));
        if (obj == null)
            Debug.LogError("assets name is not existed" + assetName);
        if (action != null)
            action.Invoke(obj);
    }
#endif

    BundleData GetBundle(string name)
    {
        BundleData bundle = null;
        if (m_AssetBundles.TryGetValue(name, out bundle))
        {
            bundle.Count++;
            return bundle;
        }
        return null;
    }
    //加载UI
    public void LoadUI(string assetName,Action<UObject> action = null)
    {
        LoadAsset(PathUtil.GetUIPath(assetName), action);
    }

    //加载Music
    public void LoadMusic(string assetName, Action<UObject> action = null)
    {
        LoadAsset(PathUtil.GetMusicPath(assetName), action);
    }

    //加载Sound
    public void LoadSound(string assetName, Action<UObject> action = null)
    {
        LoadAsset(PathUtil.GetSoundPath(assetName), action);
    }

    //加载Scene
    public void LoadScene(string assetName, Action<UObject> action = null)
    {
        LoadAsset(PathUtil.GetScenePath(assetName), action);
    }

    //加载Lua
    public void LoadLua(string assetName, Action<UnityEngine.Object> action = null)
    {
        LoadAsset(assetName, action);
    }

    //加载Effect
    public void LoadEffect(string assetName, Action<UObject> action = null)
    {
        LoadAsset(PathUtil.GetEffectPath(assetName), action);
    }
    //加载Effect
    public void LoadPrefab(string assetName, Action<UObject> action = null)
    {
        LoadAsset(assetName, action);
    }

    //卸载资源
    internal void UnLoadBundle(UObject obj)
    {
        AssetBundle ab = obj as AssetBundle;
        ab.Unload(true);
    }

    private void OnCompleted(UObject obj)
    {
        GameObject go = Instantiate(obj) as GameObject;
        go.transform.SetParent(this.transform);
        go.SetActive(true);
        go.transform.localPosition = Vector3.zero;
    }
}
